import { LoginResponse } from '@/api/types'
import { USER_INFO_KEY } from '@/hooks/use-user-data'
import axios, { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosHeaders } from 'axios'

const whiteList = ['/auth/login']

class Request {
  private instance: AxiosInstance

  constructor() {
    this.instance = axios.create({
      baseURL: import.meta.env.VITE_API_URL,
      timeout: 10000,
    })

    this.setupInterceptors()
  }

  private setupInterceptors() {
    // Request interceptor
    this.instance.interceptors.request.use(
      (config) => {
        if (!whiteList.includes(config.url || '')) {
          const userInfo = localStorage.getItem(USER_INFO_KEY) as LoginResponse['data'] | null
          if (userInfo) {
            if (!config.headers) {
              config.headers = new AxiosHeaders()
            }
            config.headers.set('userId', userInfo.userId)
          }
        }
        return config
      },
      (error) => {
        return Promise.reject(error)
      }
    )

    // Response interceptor
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        if (response.status === 200) {
          return response.data
        }
        return response
      },
      (error) => {
        if (error.response?.status === 401) {
          window.location.href = '/auth/login'
        }
        return Promise.reject(error)
      }
    )
  }

  public async get<T>(url: string, config?: InternalAxiosRequestConfig): Promise<T> {
    return this.instance.get(url, config)
  }

  public async post<T, D = Record<string, unknown>>(url: string, data?: D, config?: InternalAxiosRequestConfig): Promise<T> {
    return this.instance.post(url, data, config)
  }

  public async put<T, D = Record<string, unknown>>(url: string, data?: D, config?: InternalAxiosRequestConfig): Promise<T> {
    return this.instance.put(url, data, config)
  }

  public async delete<T>(url: string, config?: InternalAxiosRequestConfig): Promise<T> {
    return this.instance.delete(url, config)
  }
}

const request = new Request()

export default request
